package com.zqweb.gulimall.member.service.impl;

import com.zqweb.common.vo.GiteeSocialUserInfo;
import com.zqweb.common.vo.GiteeUserInfo;
import com.zqweb.gulimall.member.exception.PhoneException;
import com.zqweb.gulimall.member.exception.UserNameException;
import com.zqweb.gulimall.member.service.MemberLevelService;
import com.zqweb.gulimall.member.vo.UserLoginVo;
import com.zqweb.gulimall.member.vo.UserRegistVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zqweb.common.utils.PageUtils;
import com.zqweb.common.utils.Query;

import com.zqweb.gulimall.member.dao.MemberDao;
import com.zqweb.gulimall.member.entity.MemberEntity;
import com.zqweb.gulimall.member.service.MemberService;


@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {
    @Autowired
    private MemberLevelService memberLevelService;
    @Autowired
    private MemberDao memberDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public void registerUser(UserRegistVo userRegistVo) {
        MemberEntity memberEntity = new MemberEntity();
        /*
         根据传入的注册用户信息，给memberEntity进行必要的属性设置，然后再来实现存储
         同时，需要特别对注册的userName及phoneNumber进行查询校验，防止重复注册，即已经
         注册过在相关表中已经有注册记录了，就抛出相关的异常，不要继续存储了
          */
        // 设置默认的会员等级id（视频中又特地用MemberLevelService进行了查询，但既然是默认的，直接用已知值设置即可！）
        memberEntity.setLevelId(1L);
        // 校验userName和phoneNumber，检查是否有重复注册，有就抛出相应的异常
        String userName = userRegistVo.getUserName();
        String phoneNumber = userRegistVo.getPhoneNumber();
        // 如果userName或phoneNumber发生重复抛出相关异常，则直接由MemberController捕捉，是不会继续后面的代码的
        checkUserNameIfRepeated(userName);
        checkPhoneNumberIfRepeated(phoneNumber);
        // 当注册用的用户名和手机号没有发生重复，才继续设置要添加的注册用户的用户名和手机号信息，并将这些信息插入到数据库中
        memberEntity.setUsername(userName);
        memberEntity.setMobile(phoneNumber);
        // 设置加密后的用户密码（明文 ——> 密文）
        String sourcePW = userRegistVo.getPassword();
        String bcryptEncodedPW = new BCryptPasswordEncoder().encode(sourcePW);
        memberEntity.setPassword(bcryptEncodedPW);
        // 其他默认信息，根据需要设置到memberEntity中

        // 将成功设置所需必要信息后的userRegistVo存储到数据库表中
        memberDao.insert(memberEntity);

    }

    @Override
    public MemberEntity login(UserLoginVo userLoginVo) {
        // 登录表单提交的账户名可能是userName或phone
        String userAccount = userLoginVo.getUserAccount();
        MemberEntity memberEntity = this.baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("username", userAccount).or().eq("mobile", userAccount));
        if(memberEntity == null){
            return null;
        }else{
            String password = userLoginVo.getPassword();// 登录时传入的密码明文
            String encodedPW = memberEntity.getPassword();// 从数据库查询出的编码过的密文
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            if(bCryptPasswordEncoder.matches(password,encodedPW)){// 登录的密码是否与数据库的密文匹配
                return memberEntity;
            }else{
                return null;
            }
        }
    }

    @Override
    /*
     判断当前社交用户的uId，是否在数据库有过记录，若有表示该社交账号已登陆过，需重新设置下accessToken及过期时间
     若没有表示未登陆过，需要将该社交账号注册到member表中
      */
    public MemberEntity loginByThirdparty(GiteeSocialUserInfo giteeSocialUserInfo) {
        MemberEntity memberEntity = new MemberEntity();
        long uid = giteeSocialUserInfo.getId();
        MemberEntity realEntity = this.baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("social_uid", uid));
        if(realEntity != null){
            BeanUtils.copyProperties(realEntity,memberEntity);
            memberEntity.setId(realEntity.getId());
            memberEntity.setAccessToken(giteeSocialUserInfo.getAccess_token());
            memberEntity.setExpiresIn(giteeSocialUserInfo.getExpires_in());
            this.baseMapper.updateById(memberEntity);
        }else{
            memberEntity.setSocialUid(giteeSocialUserInfo.getId());
            memberEntity.setAccessToken(giteeSocialUserInfo.getAccess_token());
            memberEntity.setExpiresIn(giteeSocialUserInfo.getExpires_in());
            memberEntity.setEmail(giteeSocialUserInfo.getEmail());
            memberEntity.setUsername(giteeSocialUserInfo.getName());
            memberEntity.setNickname(giteeSocialUserInfo.getName());
            memberEntity.setCreateTime(new Date());
            this.baseMapper.insert(memberEntity);
        }
        return memberEntity;
    }

    // 校验userName和phoneNumber，检查是否有重复注册，有就抛出相应的异常
    private void checkUserNameIfRepeated(String userName) throws UserNameException{
        Integer userCount = memberDao.selectCount(new QueryWrapper<MemberEntity>().eq("username", userName));
        if(userCount > 0){
            throw new UserNameException();
        }
    }
    private void checkPhoneNumberIfRepeated(String phoneNumber) throws PhoneException{
        Integer phoneCount = memberDao.selectCount(new QueryWrapper<MemberEntity>().eq("mobile", phoneNumber));
        if(phoneCount > 0){
            throw new PhoneException();
        }
    }


}